package progress_bar

import (
	"fmt"
	"strings"
)

// Bar 进度条
// 在终端上打印出进度条
type Bar struct {
	percent int64  //百分比
	cur     int64  //当前进度位置
	total   int64  //总进度
	rate    string //进度条
	graph   string //显示符号
}

/*-----------------------初始化----------------------*/

/*为了能够方便地调用该进度条工具，因此，为该结构提供了两个初始化的方法，
分别为NewOption和NewOptionWithGraph,第二个初始化的方法即可以自己指定显示图案。*/

// NewOption 使用的是默认的显示图案，也就是上图展示的方框。其实现代码如下所示：
func (bar *Bar) NewOption(start, total int64) {
	bar.cur = start
	bar.total = total
	if bar.graph == "" {
		bar.graph = "#"
	}
	bar.percent = bar.getPercent()
	for i := 0; i < int(bar.percent); i += 2 {
		bar.rate += bar.graph //初始化进度条位置
	}
}

// getPercent 进度条百分比
func (bar *Bar) getPercent() int64 {
	return int64(float32(bar.cur) / float32(bar.total) * 100)
}

// NewOptionWithGraph 第二个初始化函数就比较容易实现了，只需要把graph重新覆盖之后，直接调用上面的初始化函数即可。
func (bar *Bar) NewOptionWithGraph(start, total int64, graph string) {
	bar.graph = graph
	bar.NewOption(start, total)
}

// Play 进度条展示
// 一般调用显示进度条时，都是放在循环中执行的，因此，我们只需要在循环中能够展示出每轮循环当前的进度状态即可。
// 这段代码中，最重要的就是最后的使用fmt.Printf打印的那一句，通过\r控制打印效果。
// 当然了，在构建rate进度条时，我需要保存上一次完成的百分比，只有当百分比发生了变化，且步长变化了2时，才需要改变进度条的长度。
// 如果你的屏幕足够大，你也可以让你的进度条长度为100个字符，这样，你就不需要控制进度条的步长为2了，每增长1%，进度条前进1格，也是没有问题的。
func (bar *Bar) Play(cur int64) {
	bar.cur = cur
	last := bar.percent
	bar.percent = bar.getPercent()
	if bar.percent != last {
		bar.rate = strings.Repeat(bar.graph, int(bar.percent/2))
	}
	fmt.Printf("\r	[%-50s]%3d%%  %8d/%d \n", bar.rate, bar.percent, bar.cur, bar.total)
}

// Finish 结束
// 由于上面的打印没有打印换行符，因此，在进度全部结束之后（也就是跳出循环之外时），
// 需要打印一个换行符，因此，封装了一个Finish函数，该函数纯粹的打印一个换行，表示进度条已经完成。
func (bar *Bar) Finish() {
	fmt.Println()
}
